package com.heima.media.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.dto.ResponseResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.minio.MinIOService;
import com.heima.common.util.SensitiveWordUtil;
import com.heima.media.dto.ArticleDto;
import com.heima.media.dto.ContentDto;
import com.heima.media.dto.ImageDto;
import com.heima.media.entity.WmChannel;
import com.heima.media.entity.WmNews;
import com.heima.media.entity.WmSensitive;
import com.heima.media.entity.WmUser;
import com.heima.media.feign.ArticleFeign;
import com.heima.media.service.*;
import org.apache.commons.io.IOUtils;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class AuditServiceImpl implements IAuditService {

    @Autowired
    private IWmNewsService newsService;

    @Autowired
    private IWmUserService userService;

    @Autowired
    private IWmChannelService channelService;

    @Autowired
    private GreenTextScan textScan;

    @Autowired
    private GreenImageScan imageScan;

    @Autowired
    private ArticleFeign articleFeign;

    @Autowired
    private MinIOService minIOService;

    @Autowired
    IWmSensitiveService wmSensitiveService;

    @Override
    @Async
    public void audit(Integer id) {


    }

    @Override
    @Async
    public void audit(WmNews news) {

        System.out.println(Thread.currentThread().getName() + " 开始自动审核服务..." + new Date());

        if (news.getStatus() == 8 || news.getStatus() == 4) {

            if (news.getPublishTime().getTime() <= System.currentTimeMillis()) {

                publishArticle(news);

                return;
            }
        }
        if (news.getStatus() == 1) {

            Map<String, Object> map = getTextAndImagesFromContent(news.getContent());

            String text = (String) map.get("text");

            List<String> images = (List<String>) map.get("images");

            boolean sensitiveResult = checkSensitiveServiceImpl(text, news);

            if (!sensitiveResult) {
                return;
            }
            boolean textResult = checkText(news, text);

            if (!textResult) return;

            boolean imageResult = checkImages(news, images);

            if (!imageResult) return;

            if (news.getPublishTime().getTime() > System.currentTimeMillis()) {

                news.setStatus(8);

                newsService.updateById(news);

                RQueue<String> queue = redissonClient.getBlockingQueue("publish-article");

                RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(queue);

                long time = news.getPublishTime().getTime() - System.currentTimeMillis();

                String message = JSON.toJSONString(news);

                delayedQueue.offer(message, time, TimeUnit.MILLISECONDS);
            } else {

                publishArticle(news);
            }
        }
        System.out.println(Thread.currentThread().getName() + " 自动审核服务执行完成" + new Date());
    }

    @Autowired
    private RedissonClient redissonClient;

    private boolean checkSensitiveServiceImpl(String text, WmNews news) {

        boolean result = false;

        if (SensitiveWordUtil.dictionaryMap.size() <= 0) {

            LambdaQueryWrapper<WmSensitive> query = new LambdaQueryWrapper<>();

            query.select(WmSensitive::getSensitives);

            List<String> list = wmSensitiveService.listObjs(query, O -> O.toString());

            SensitiveWordUtil.initMap(list);
        }

        Map<String, Integer> stringIntegerMap = SensitiveWordUtil.matchWords(news.getTitle());

        if (stringIntegerMap.size() <= 0) {

            Map<String, Integer> stringIntegerMap1 = SensitiveWordUtil.matchWords(text);

            if (stringIntegerMap1.size() <= 0) {

                result = true;
            } else {

                news.setStatus(2);

                Set<String> strings = stringIntegerMap1.keySet();

                String join = String.join(",", strings);

                news.setReason("敏感词不通过：" + join);

                newsService.updateById(news);
            }
        } else {

            news.setStatus(2);

            Set<String> strings = stringIntegerMap.keySet();

            String join = String.join(",", strings);

            news.setReason("敏感词不通过：" + join);

            newsService.updateById(news);
        }
        return result;
    }

    private boolean checkImages(WmNews news, List<String> images) {

        boolean result = false;

        List<ImageDto> list = JSON.parseArray(news.getImages(), ImageDto.class);

        for (ImageDto imageDto : list) {

            if (!images.contains(imageDto.getUrl())) {

                images.add(imageDto.getUrl());
            }
        }

        if (images.size() == 0) {

            return true;
        }

        try {
            List<byte[]> imageBytes = new ArrayList<>();

            for (String image : images) {

                InputStream download = minIOService.download(image);

                byte[] bytes = IOUtils.toByteArray(download);

                imageBytes.add(bytes);
            }

            Map map = imageScan.imageScan(imageBytes);

            String suggestion = (String) map.get("suggestion");

            switch (suggestion) {
                case "pass":
                    result = true;
                    break;
                case "review":
                    // 人工审核 状态为 3
                    news.setStatus(3);
                    newsService.updateById(news);
                    break;
                case "block":
                    // 更新wmNews状态为 2 审核失败  记录失败原因
                    news.setStatus(2);
                    String label = (String) map.get("label");
                    news.setReason("阿里云图片审核失败: " + label);
                    newsService.updateById(news);
                    break;
            }
        } catch (Exception e) {

            e.printStackTrace();
        }
        return result;
    }

    private boolean checkText(WmNews news, String text) {

        boolean result = false;

        String s = news.getTitle() + text;

        System.out.println("标题是：" + news.getTitle());

        System.out.println("文章内容是：" + text);

        try {
            Map map = textScan.greenTextScan(s);

            String suggestion = (String) map.get("suggestion");

            switch (suggestion) {

                case "pass":

                    result = true;

                    break;

                case "review":
                    // 人工审核 状态为 3
                    news.setStatus(3);

                    newsService.updateById(news);

                    break;

                case "block":

                    news.setStatus(2);

                    String label = (String) map.get("label");

                    news.setReason("阿里云审核失败：" + label);

                    newsService.updateById(news);

                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;

    }

    private void publishArticle(WmNews news) {

        ArticleDto articleDto = new ArticleDto();

        System.out.println(news);

        BeanUtils.copyProperties(news, articleDto);

        articleDto.setId(null);

        WmUser byId = userService.getById(news.getUserId());

        articleDto.setAuthorId(byId.getApAuthorId());

        articleDto.setAuthorName(byId.getName());

        System.out.println("频道的id号是" + news.getChannelId());

        WmChannel byId1 = channelService.getById(news.getChannelId());

        articleDto.setChannelName(byId1.getName());

        articleDto.setLayout(news.getType());

        articleDto.setFlag(0);

        String images = news.getImages();

        List<ImageDto> list = JSON.parseArray(images, ImageDto.class);

        List<String> imageList = new ArrayList<>();

        for (ImageDto imageDto : list) {

            imageList.add(imageDto.getUrl());
        }

        String imageStr = String.join(",", imageList);

        articleDto.setImages(imageStr);

        ResponseResult<Long> longResponseResult = articleFeign.saveArticle(articleDto);

        if (longResponseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {

            Long data = longResponseResult.getData();

            news.setArticleId(data);

            news.setStatus(9);

            newsService.updateById(news);
        }
    }

    private Map<String, Object> getTextAndImagesFromContent(String content) {

        Map<String, Object> map = new HashMap<>();

        StringBuilder text = new StringBuilder();

        List<String> images = new ArrayList<>();

        List<ContentDto> contentDtos = JSON.parseArray(content, ContentDto.class);

        for (ContentDto contentDto : contentDtos) {

            if (contentDto.getType().equals("text")) {

                text.append(contentDto.getValue());
            } else {

                images.add(contentDto.getValue());
            }
        }

        map.put("text", text.toString());
        map.put("images", images);
        return map;
    }
}
